namespace SimpleWebServices.Globalization
{
    using System;
    using System.Collections;
    using System.Collections.Generic;
    using System.Globalization;
    using System.Linq;
    using System.Text;
    using System.Threading;
    using System.Xml;
    using System.Xml.Schema;
    using System.Xml.Serialization;

    [XmlRoot("translations")]
    public sealed class TranslationCollection<T> : IEnumerable, IEnumerable<T>, IXmlSerializable
    {
        private Dictionary<Language, T> _data;

        public TranslationCollection()
        {
            this._data = new Dictionary<Language, T>();
        }

        public int Count
        {
            get
            {
                return this._data.Count;
            }
        }

        public T Current
        {
            get
            {
                T value = default(T);

                if (0 != this.Count)
                {
                    CultureInfo current = Thread.CurrentThread.CurrentUICulture;
                    if (this._data.ContainsKey(current))
                    {
                        value = this[current.Name];
                    }
                    else if (5 == current.Name.Length && this._data.ContainsKey(current.Name.Substring(0, 2)))
                    {
                        value = this[current.Name.Substring(0, 2)];
                    }
                    else if (this._data.ContainsKey(CultureInfo.InvariantCulture))
                    {
                        value = this[CultureInfo.InvariantCulture.Name];
                    }
                    else
                    {
                        value = this._data.ElementAt(0).Value;
                    }
                }

                return value;
            }
        }

        public T this[string language]
        {
            get
            {
                return this._data[language];
            }

            set
            {
                this._data[language] = value;
            }
        }

        public void Add(Language language, T value)
        {
            this._data.Add(language, value);
        }

        public void Clear()
        {
            this._data.Clear();
        }

        public void Remove(Language language)
        {
            this._data.Remove(language);
        }

        public override string ToString()
        {
            StringBuilder buffer = new StringBuilder();
            foreach (var item in this._data)
            {
                if (0 != buffer.Length)
                {
                    buffer.Append(Environment.NewLine);
                }

                buffer.AppendFormat(CultureInfo.InvariantCulture, "{0}={1}", item.Key, item.Value.ToString());
            }

            return buffer.ToString();
        }

        public IEnumerator GetEnumerator()
        {
            return (this._data as IEnumerable).GetEnumerator();
        }

        IEnumerator<T> IEnumerable<T>.GetEnumerator()
        {
            return (this._data.Values as IEnumerable<T>).GetEnumerator();
        }

        XmlSchema IXmlSerializable.GetSchema()
        {
            throw new NotSupportedException();
        }

        void IXmlSerializable.ReadXml(XmlReader reader)
        {
            if (null == reader)
            {
                throw new ArgumentNullException("reader");
            }

            if (reader.IsEmptyElement)
            {
                reader.Read();
            }
            else
            {
                string name = reader.Name;
                reader.Read();
                while (true)
                {
                    if (XmlNodeType.None == reader.NodeType)
                    {
                        break;
                    }
                    else if (XmlNodeType.EndElement == reader.NodeType && reader.Name == name)
                    {
                        reader.Read();
                        break;
                    }
                    else
                    {
                        this._data.Add(reader.GetAttribute("xml:lang") ?? string.Empty, reader.ReadInnerXml().Deserialize<T>());
                    }
                }
            }
        }

        void IXmlSerializable.WriteXml(XmlWriter writer)
        {
            if (null == writer)
            {
                throw new ArgumentNullException("writer");
            }

            foreach (var item in this._data)
            {
                writer.WriteStartElement("translation");
                if (item.Key != CultureInfo.InvariantCulture)
                {
                    writer.WriteAttributeString("xml:lang", item.Key);
                }

                writer.WriteRaw(item.Value.Serialize().CreateNavigator().OuterXml);
                writer.WriteEndElement();
            }
        }
    }
}